

import java.awt.event.MouseListener;
import javax.comm.UnsupportedCommOperationException;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class Tabuleiro extends JPanel {

	private static final long serialVersionUID = 1L;
	
	//armazena a matriz de espa�os
	private Espaco tabuleiro[][];
	
	//dist�ncia entre os espa�os
	private int distancia;
	
	//tamanho da matriz
	public final int MAX = 7;
	
	//armazena o espa�o atual na matriz
	private Espaco espaco;
	
	//armazena o main que chamou o tabuleiro
	private Jogo main;
	

	//construtor
	public Tabuleiro(int posY, int posX, int dimensao, Jogo main){
		
		this.main = main;
		
		tabuleiro = new Espaco[MAX][MAX];
		
		distancia = (int)(0.00625 * dimensao);
		
		setBounds(posY, posX, dimensao + distancia * 5, dimensao + distancia);

		
		//instancia matriz de Espa�os
		for (int x=0;x<MAX;x++){
			for (int y=0;y<MAX;y++){
				tabuleiro[x][y] = new Espaco( (dimensao / MAX), null  );
			}
		}
		
		setLayout(null);
		desenha();
		iniciaPersonagens();

	}
	
	//inicia a posi��o dos personagens
	private void iniciaPersonagens(){
		
		//Gansos
		
		for (int x=0; x < MAX; x++){
			tabuleiro[4][x].setPersonagem(new Ganso());
		}
		
		for (int x= (int)(MAX / 1.5); x<MAX; x++){
			for (int y=(MAX / 3); y < (MAX / 1.5); y++) {
				if (tabuleiro[x][y].getPersonagem() == null){
					tabuleiro[x][y].setPersonagem(new Ganso()) ;
					
				}
			}
			
		}
		
		//Raposa
		tabuleiro[2][3].setPersonagem(new Raposa());
		
	}
	
	//insere um espa�o no tabuleiro (utilizado por desenha() )
	private void insereEspaco(int x, int y){
		Espaco e = tabuleiro[x][y];
		e.setPosicao( x* ( tabuleiro[x][y].getWidth() + distancia), y* ( tabuleiro[x][y].getHeight() + distancia) );
		e.setName("E"+String.valueOf(y)+String.valueOf(x));
		add(e);
	}
	
	private void desenha(){
		
		for (int x=MAX/3; x< (MAX / 1.5); x++){
			for (int y=0;y<MAX;y++) insereEspaco(x, y);
		}
		
		for (int x=0; (x < MAX / 3); x++){
			for (int y=(MAX / 3); y < (MAX / 1.5); y++) insereEspaco(x, y);
		}
		
		for (int x= (int)(MAX / 1.5); x<MAX; x++){
			for (int y=(MAX / 3); y < (MAX / 1.5); y++)insereEspaco(x, y);
		}
		
	}


	//ao implementar um MouseListener, implementa tambem para todos os seus espa�os
	@Override
	public synchronized void addMouseListener(MouseListener arg0) {
		//atribui um mouselistener a cada um de seus espa�os
		for (int x=0;x<MAX;x++){
			for (int y=0;y<MAX;y++){
				tabuleiro[x][y].addMouseListener(arg0);
			}
		}
		super.addMouseListener(arg0);
	}
	
	private boolean exclui(Espaco origem, Espaco destino){
		int origemY = Integer.parseInt( origem.getName().substring(1, 2));
		int origemX = Integer.parseInt( origem.getName().substring(2, 3));		
		int destinoY = Integer.parseInt( destino.getName().substring(1, 2));
		int destinoX = Integer.parseInt( destino.getName().substring(2, 3));

		int maiorX, maiorY, menorX, menorY;
		
		if (origemX > destinoX) {
			maiorX = origemX;
			menorX = destinoX;
		} else {
			maiorX = destinoX;
			menorX = origemX;
		}
		
		if (origemY > destinoY) {
			maiorY = origemY;
			menorY = destinoY;
		} else {
			maiorY = destinoY;
			menorY = origemY;
		}
		//excluir se a dist�ncia for superior a um quadro
		if ( (maiorX - menorX > 1) || (maiorY - menorY > 1) ){
			Espaco e = tabuleiro[(maiorX + menorX) / 2][(maiorY + menorY) / 2];
			e.setPersonagem(null);
			System.gc();
			return true;
		}
		
		return false;
		
	}
	
	
	//move personagem do espa�o origem para o espa�o destino
	public void movePersonagem(Espaco origem, Espaco destino){
		
		//TODO verifica se deve excluir
		boolean e = exclui(origem, destino);
		
		destino.setPersonagem(origem.getPersonagem());
		origem.setPersonagem(null);
		setEspaco(destino);
		
		if ( (e) && (main.getTurn() == Raposa.class) && ( setMoveables(getEspaco()) > 0 ) ){
			JOptionPane.showMessageDialog(null, "Jogue de novo");
		}else main.changeTurno();

                SimpleWrite portWrite;

                portWrite = new SimpleWrite();

                String str = new String("m");
                str = str + origem.getPx() + origem.getPy() + destino.getPx() + origem.getPy();

                try {
                    portWrite.write(str);
                } catch (UnsupportedCommOperationException ex) {
                    System.out.print(ex);
                }

		
		
	}
	
	private boolean isPosicaoEspecial(Espaco e2, Espaco e3){
		//e2 = posi��o intermediaria
		//e3 = posi��o destino
		if ( (e2 == null) || (e3 == null) ) return false;
		if ( (e2.getName() == null) || (e3.getName() == null) ) return false;
		if ( (e2.getPersonagem() != null) && ( e3.getPersonagem() == null) ) return true; else return false;
		
	}
	
	//seta os espa�os poss�veis de movimenta��o
	public int setMoveables(Espaco e){

		int posX, posY;
		int quant = 0;  //guarda a quantidade de possibilidades de caminho
		int qtExclusoes = 0;// guarda a quantidade de possibilidades de exclus�o
		
		//setar todos como n�o moveables
		for (int x=0;x<MAX;x++){
			for (int y=0;y<MAX;y++){
				tabuleiro[x][y].setMoveable(false);
			}
		}
		
		if (e != null){
			posY = Integer.parseInt( e.getName().substring(1, 2));
			posX = Integer.parseInt( e.getName().substring(2, 3));
			
			//setar somente os moveables
			if ( ( posY + 1 < MAX ) && (tabuleiro[posX][posY + 1].getPersonagem() == null) ){
				tabuleiro[posX][posY + 1].setMoveable(true);
				quant++;
			}

			if ( ( posY - 1 >= 0) && (tabuleiro[posX][posY - 1].getPersonagem() == null) ){
				tabuleiro[posX][posY - 1].setMoveable(true);
				quant++;
			}

			if ( ( posX + 1 < MAX ) && (tabuleiro[posX + 1][posY].getPersonagem() == null) ){
				tabuleiro[posX + 1][posY].setMoveable(true);
				quant++;
			}
			
			if ( ( posX - 1 >= 0) && (tabuleiro[posX - 1][posY].getPersonagem() == null) ){
				tabuleiro[posX - 1][posY].setMoveable(true);
				quant++;
			}
			
			
			
			if (e.getPersonagem().getClass().equals(Raposa.class)){
				
			
				//posi��es especiais (com exclus�o)
				//baixo
				if ( posX + 2 < MAX ){
					if ( isPosicaoEspecial(tabuleiro[posX + 1][posY], tabuleiro[posX + 2][posY]) ){
						tabuleiro[posX + 2][posY].setMoveable(true);
						quant ++;
						qtExclusoes ++;
					}
				}
				//cima
				if ( posX - 2 >=0 ){
					if ( isPosicaoEspecial(tabuleiro[posX - 1][posY], tabuleiro[posX - 2][posY]) ){
						tabuleiro[posX - 2][posY].setMoveable(true);
						quant ++;
						qtExclusoes ++;
					}
				}
				//esquerda
				if (  posY - 2 >=0 ){
					if ( isPosicaoEspecial(tabuleiro[posX][posY - 1], tabuleiro[posX][posY - 2]) ){
						tabuleiro[posX][posY - 2].setMoveable(true);
						quant ++;
						qtExclusoes ++;
					}
				}
				//direita
				if ( posY + 2 < MAX ){
					if ( isPosicaoEspecial(tabuleiro[posX][posY + 1], tabuleiro[posX][posY + 2]) ){
						tabuleiro[posX][posY + 2].setMoveable(true);
						quant ++;
						qtExclusoes ++;
					}
				}
				
				if (quant == 0){
					win(Ganso.class);
				}
			
			}
			
			if (Ganso.getQuant() <= 3){
				win(Raposa.class);
			}
			
			//setar o espa�o selecionado
			e.setSelected(true);		
		}
		
		return qtExclusoes;
			
	}
	
	private void win(Class c){
		main.win(c);
	}
	
	//setters e getters
	public int getDistancia() {
		return distancia;
	}

	public void setDistancia(int distancia) {
		this.distancia = distancia;
	}
	
	public Espaco getEspaco() {
		return espaco;
	}

	public void setEspaco(Espaco e) {
		this.espaco = e;
		setMoveables(espaco);
	}
	
}
